package core

import (
	"buding-ai/pkg/config"
	"context"
	"log"
	"os"
	"time"

	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readpref"
)

var (
	MongoClient   *mongo.Client
	MongoDB       *mongo.Database
	MsgCollection *mongo.Collection
	MongoLogger   *log.Logger
)

func init() {
	// 初始化日志
	MongoLogger = log.New(os.Stdout, "[MongoDB] ", log.LstdFlags)

	// 获取MongoDB配置
	cfg := config.GetConfig().MongoDB

	// 设置连接选项
	clientOptions := options.Client().ApplyURI(cfg.URI)

	// 设置连接池配置
	clientOptions.SetMaxPoolSize(100)                  // 最大连接数
	clientOptions.SetMinPoolSize(10)                   // 最小连接数
	clientOptions.SetMaxConnIdleTime(30 * time.Minute) // 连接最大空闲时间

	// 设置超时时间
	clientOptions.SetConnectTimeout(10 * time.Second)        // 连接超时
	clientOptions.SetServerSelectionTimeout(5 * time.Second) // 服务器选择超时
	clientOptions.SetSocketTimeout(30 * time.Second)         // Socket超时

	// 设置认证信息（如果提供）
	if cfg.Username != "" && cfg.Password != "" {
		clientOptions.SetAuth(options.Credential{
			Username:   cfg.Username,
			Password:   cfg.Password,
			AuthSource: "admin",
		})
	}

	// 创建连接上下文（带超时）
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	// 连接MongoDB
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		MongoLogger.Fatalf("MongoDB连接失败: %v", err)
	}

	// 验证连接
	err = client.Ping(ctx, readpref.Primary())
	if err != nil {
		MongoLogger.Fatalf("MongoDB Ping失败: %v", err)
	}

	MongoLogger.Println("MongoDB连接成功")

	// 存储连接和数据库引用
	MongoClient = client
	MongoDB = client.Database(cfg.DBName)
	MsgCollection = MongoDB.Collection("messages")

	// 注册关闭函数
	registerMongoShutdown()
}

// registerMongoShutdown 注册关闭MongoDB连接的函数
func registerMongoShutdown() {
	// 这里应该在应用程序退出时调用
	// 可以通过信号处理或者App.Stop()中调用
	// 作为示例，我们只是记录一条日志
	MongoLogger.Println("MongoDB关闭函数已注册，将在应用退出时调用")
}

// CloseMongoConnection 关闭MongoDB连接
func CloseMongoConnection() {
	if MongoClient != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()

		if err := MongoClient.Disconnect(ctx); err != nil {
			MongoLogger.Printf("关闭MongoDB连接失败: %v", err)
			return
		}

		MongoLogger.Println("MongoDB连接已关闭")
	}
}
